package util;
import java.util.Random;

import mill.IMill;
import mill.MillPark;
import mill.components.Generator;
import mill.components.MillComponent;
import mill.components.Wing;
import mill.measurePoints.AirTemperature;
import mill.measurePoints.MeasurePoint;
import mill.measurePoints.WindDirection;
import mill.measurePoints.Windspeed;


public class Simulator extends Thread {

	private MillPark m_millPark;
	private int m_threadSleep, m_windspeed, m_windDirection;
	private double m_airTemp;
	private Random m_generator;


	public Simulator(MillPark park){
		super();

		m_millPark = park;
		

		m_airTemp = 15;
		m_windspeed = 10;
		m_windDirection = 0;
		m_generator = new Random();

		m_threadSleep = 2000 + (int)m_generator.nextDouble()*3000;
	}

	public void run(){

		while(true){
			try {
				updateWindValues();
				Thread.sleep(m_threadSleep);
			} catch (InterruptedException e) {

			}
		}
	}

	private void updateWindValues()
	{
		simulateWorld();

		int wingLength = 0;
		double density = airDensity(m_windspeed);
		double powerCalc = (int)Math.round(0.5*density*Math.pow(m_windspeed, 3)*Math.PI);
		
		for(IMill mill : m_millPark.getMills()){
			for(MeasurePoint mp : mill.getMeasurePoints()){
				if(mp instanceof Windspeed)
					((Windspeed)mp).set_windspeed(m_windspeed);

				if(mp instanceof AirTemperature)
					((AirTemperature)mp).set_measuredValue(m_airTemp);

				if(mp instanceof WindDirection)
					((WindDirection)mp).set_windDirection(m_windDirection);
			}

			for(MillComponent mc : mill.getComponents())
			{
				if(mc instanceof Wing){
					wingLength = ((Wing)mc).get_length();
					break;
				}
			}
			
			for(MillComponent mc : mill.getComponents())
			{
				if(mc instanceof Generator){
					((Generator)mc).set_powerOutput(powerCalc*wingLength);
					break;
				}
			}
		}
		
		m_millPark.notifyUpdate();
	}

	private double airDensity(double airTemp)
	{
		//y = 4,11401099E-04x2 - 2,88259615E-02x + 1,45093956
		double density = 0.0004114 *Math.pow(airTemp, 2) - 0.02882*airTemp + 1.45093956;
		return density;
	}

	private void simulateWorld()
	{
		if(m_generator.nextBoolean())
			m_airTemp += m_generator.nextDouble();
		else
			m_airTemp -= m_generator.nextDouble();

		if(m_generator.nextBoolean())
			m_windspeed += m_generator.nextInt(5);
		else
			m_windspeed -= m_generator.nextInt(5);

		if(m_generator.nextBoolean())
			m_windDirection+=m_generator.nextInt(45);
		else
			m_windDirection-=m_generator.nextInt(45);

		if(m_windspeed < 0)
			m_windspeed = 0;

		if(m_windDirection < 0)
			m_windDirection = 360 + m_windDirection;

		if(m_windDirection>360)
			m_windDirection = m_windDirection-360;
	}
}
